<?php

namespace App\Service\SearchService;

use Hyperf\Elasticsearch\ClientBuilderFactory;
use App\Service\BaseService;
use App\Service\AppService\SystemCacheConfigService;

class BaseElasticSearchClientService extends BaseService
{
    public $client;
    public $index;
    public $mapping_property = [];
    public function __construct()
    {
        $sysconfig = SystemCacheConfigService::instance()->getCacheInfoBySystemCode('elasticsearch');
        $builder = container()->get(ClientBuilderFactory::class)->create();
        $this->client = $builder->setHosts([
            $sysconfig['address'],
        ])->build();
    }
    
    /**
     * 创建文档索引模板
     */
    public function createMapping( $index = null )
    {
        $param = [
            'index' => $index ? $index : $this->index,
            'body'  => [
                'settings' => [
                    'number_of_shards'      => 3,
                    'number_of_replicas'    => 1,
                    "index.refresh_interval" => "15s",
                    'analysis'  => [
                        'pinyin_filter' => [
                            "type"  => "pinyin",
                            "keep_first_letter" => true
                        ],
                        'analyzer'  => [
                            'ik_pinyin_analyzer'   => [
                                'type'      => 'pinyin',
                                'tokenizer' => 'ik_smart',
                                'filter'    => 'pinyin_filter'
                            ]
                        ]
                    ],
                ],
                'mappings'  => [
                    'properties' => $this->mapping_property,
                ]
            ]
        ];
        return $this->client->indices()->create($param);
    }
    
    /**
     * 关闭索引使用
     * @param unknown $index
     */
    public function closeIndex( $index = null )
    {
        $index = $index ? $index : $this->index;
        $param = [
            'index' => $index,
        ];
        return $this->client->indices()->close($param);
    }    

    /**
     * 开启索引使用
     * @param unknown $index
     */
    public function openIndex( $index = null )
    {
        $index = $index ? $index : $this->index;
        $param = [
            'index' => $index,
        ];
        return $this->client->indices()->open($param);
    }
    
    /**
     * 开启索引使用
     * @param unknown $index
     */
    public function putIndexSetting( $index = null )
    {
        $index = $index ? $index : $this->index;
        $param = [
            'index' => $index,
            'body'  => [
                'index' => [
                    'analysis'  => [
                        'analyzer'  => [
                            'ik_pinyin_analyzer'    => [
                                'type'      => 'custom',
                                'tokenizer' => 'ik_max_word',
                                'filter'    => 'pinyin_filter'
                            ],
                        ],
                        'filter' => [
                            'pinyin_filter' => [
                                'type'  => 'pinyin',
                                'keep_first_letter'=> false
                            ]
                        ]
                    ]
                ]
            ]
        ];
        return $this->client->indices()->putSettings($param);
    }
    
    /**
     * 分词分析
     */
    public function analyze( string $keyword )
    {
        $keyword = str_replace(" ", "", $keyword);
        $param = [
            'body'  => [
                'analyzer'  =>  'ik_smart',
                'text'      =>  $keyword
            ]
        ];
        return $this->client->indices()->analyze($param);
    }
    
    /**
     * 添加文档
     */
    public function addDoc($param)
    {
        return $this->client->create($param);
    }
    
    /**
     * write with block
     */
    public function bulk($param)
    {
        $param = [
            'body'  => $param,
        ];
        return $this->client->bulk($param);
    }
    
    /**
     * delete all
     */
    public function deleteByQuery( $param = [] )
    {
        return $this->client->deleteByQuery($param);
    }
    
    /**
     * Deletes an index.
     */
    public function delMapping( $index = null)
    {
        $index = $index ? $index : $this->index;
        $param = [
            'index' => $index,
        ];
        return $this->client->indices()->delete($param);
    }
    
    /**
     * get Index Mapping
     */
    public function getMapping( $index = null )
    {
        $index = $index ? $index : $this->index;
        $param = [
            'index' => $index,
        ];
        return $this->client->indices()->getMapping($param);
    }
    
    /**
     * 获取索引
     */
    public function getIndices( $index = null )
    {
        $index = $index ? $index : $this->index;
        $param = [
            'index' => $index,
        ];
        return $this->client->cat()->indices($param); 
    }
    
    /**
     * 获取全部的索引
     */
    public function getAllIndices()
    {
        return $this->client->cat()->indices();
    }
    
    /**
     * 判断索引是否存在
     */
    public function existsIndices( $index = null)
    {
        $index = $index ? $index : $this->index;
        $param = [
            'index' => $index,
        ];
        return $this->client->indices()->exists($param);
    }
    
    /**
     * 分组数据
     * @param array $param
     */
    public function getAggsList( $param = [] )
    {
        return $this->client->search($param);
    }
    
    /**
     * 搜索数据
     * @param array $param
     */
    public function searchDataFromIndex( $param = [], $index = null )
    {
        $index = $index ? $index : $this->index;
        $page  = $param['page'] ?? 0;
        $limit = $param['limit'] ?? 10;
        $body = [
            'track_total_hits'  => true,
            'index' => $index,
            '_source' => $param['_source']??[],
            'body'  => [
                'query' => $param['query'] ?? []
            ] ,
            'from'  => $page,
            'size'  => $limit,
        ];
        
        if( !empty($param['sort']) ) {
            $body['body']['sort'] = $param['sort'];
        }
        
        if( !empty($param['highlight']) ) {
            $body['body']['highlight'] = $param['highlight'];
        }
        
        $list = $this->client->search($body);
        $temArr = [];
        array_map(function( $value ) use ( & $temArr ) {
            $temArr[$value['_id']] = $value['_source'];
        }, $list['hits']['hits']);
        rsort($temArr);
        $pageData = [
            'page'  => $page,
            'limit' => $limit,
            'total' => $list['hits']['total']['value'],
            'list'  => $temArr
        ];
        return $pageData;
    }
}